﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System {
    /// <summary>
    /// 解构赋值
    /// </summary>
    public static class Assigns {
        /// <summary>
        /// 解构拷贝对象属性，将右值的属性解构拷贝到左值的属性
        /// </summary>
        /// <typeparam name="TLeft">左值类型</typeparam>
        /// <typeparam name="TRight">右值类型</typeparam>
        /// <param name="left">左值</param>
        /// <param name="right">右值</param>
        /// <returns>true: 1. 右值存在属性被拷贝到左值属性</returns>
        public static bool Aceept<TLeft, TRight>(this TLeft left, TRight right) {
            if (left?.Equals(right) ?? false) return true;

            bool retHasAssigned = false;
            var leftProps = typeof(TLeft).GetProperties();
            var rightProps = typeof(TRight).GetProperties();

            foreach (var leftProp in leftProps) {
                var rightProp = rightProps.FirstOrDefault(it => it.Name == leftProp.Name);
                // 右值 不存在 对应的属性, 不做赋值
                if (rightProp == null) continue; 

                //左值类型 与 右值类型 不相同, 不做赋值
                if (!leftProp.PropertyType.Equals(rightProp.PropertyType)) continue;

                ////试图对 非(值类型、字符串类型) 的属性进行 递归深拷贝
                if (!(leftProp.PropertyType.IsValueType || leftProp.PropertyType.Equals(typeof(string)))) {
                    if (!retHasAssigned) {                        
                        retHasAssigned = Aceept(leftProp.GetValue(left), rightProp.GetValue(right));
                    }
                }

                //试图对 值类型、字符串类型 的属性进行赋值
                if (!(leftProp.GetValue(left)?.Equals(rightProp.GetValue(right)) ?? false)) {
                    leftProp.SetValue(left, rightProp.GetValue(right));
                    if (!retHasAssigned) {
                        retHasAssigned = true;
                    }
                }
            }

            return retHasAssigned;
        }
    }
}
